﻿using System;

using Tszy.Unlimited.Base.Collections;

namespace Tszy.Unlimited.Data.AdoNet.Sql.Common
{
    internal class DataModelManager
    {
        #region 线程安全单例

        private static DataModelManager _instance;
        private static readonly object _lockObject = new();

        /// <summary>
        /// 单例。
        /// </summary>
        public static DataModelManager Instance
        {
            get
            {
                if (_instance == null)
                {
                    lock (_lockObject)
                    {
                        if (_instance == null)
                        {
                            _instance = new DataModelManager();
                        }
                    }
                }

                return _instance;
            }
        }

        #endregion 线程安全单例

        private readonly MonoConcurrentDictionary<string, DataModelResult> _datatables = new();

        /// <summary>
        /// 获得表名。
        /// </summary>
        /// <typeparam name="TSource"></typeparam>
        /// <returns></returns>
        public string GetTableName<TSource>(string prdfix = "")
        {
            return GetTableName(prdfix, typeof(TSource));
        }

        /// <summary>
        /// 获得表名。
        /// </summary>
        /// <returns></returns>
        public string GetTableName(string prdfix, Type type)
        {
            var key = type.FullName ?? string.Empty;

            Init(prdfix, key, type);

            return _datatables[key]?.TableName ?? string.Empty;
        }

        public string GetTableName(string prdfix, object obj)
        {
            var type = obj.GetType();

            var key = type.FullName ?? string.Empty;

            Init(prdfix, key, obj);

            return _datatables[key]?.TableName ?? string.Empty;
        }

        /// <summary>
        /// 获得主键名。
        /// </summary>
        /// <typeparam name="TSource"></typeparam>
        /// <returns></returns>
        public string GetTableKey<TSource>(string prdfix = "")
        {
            return GetTableKey(prdfix, typeof(TSource));
        }

        public string GetTableKey(string prdfix, Type type)
        {
            var key = type.FullName ?? string.Empty;

            Init(prdfix, key, type);

            return _datatables[key]?.TableKey ?? string.Empty;
        }

        public string GetTableKey(string prdfix, object obj)
        {
            var type = obj.GetType();

            var key = type.FullName ?? string.Empty;

            Init(prdfix, key, obj);

            return _datatables[key]?.TableKey ?? string.Empty;
        }

        #region 初始化数据库信息

        private void Init(string prdfix, string key, Type type)
        {
            Init(prdfix, key, Activator.CreateInstance(type));
        }

        private void Init(string prdfix, string key, object obj)
        {
            if (_datatables.ContainsKey(key))
            {
                return;
            }

            lock (_lockObject)
            {
                if (_datatables.ContainsKey(key))
                {
                    return;
                }

                var result = new DataModelResult
                {
                    DataType = obj.GetType()
                };

                var methodGetTalbeName = result.DataType.GetMethod("GetTableName");

                if (methodGetTalbeName != null)
                {
                    result.TableName = methodGetTalbeName.Invoke(obj, null)?.ToString() ?? string.Empty;
                }

                if (string.IsNullOrWhiteSpace(result.TableName))
                {
                    result.TableName = prdfix + result.DataType.Name;
                }

                var methodGetTalbeKey = result.DataType.GetMethod("GetTableKey");

                if (methodGetTalbeKey != null)
                {
                    result.TableKey = methodGetTalbeKey.Invoke(obj, null)?.ToString() ?? string.Empty;
                }

                if (string.IsNullOrWhiteSpace(result.TableKey))
                {
                    result.TableKey = "Id";
                }

                _datatables[key] = result;
            }
        }

        private class DataModelResult
        {
            public string TableName { get; set; }

            public string TableKey { get; set; }

            public Type DataType { get; set; }
        }

        #endregion 初始化数据库信息
    }
}